home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / upc12bs1.zip / UUCICO / ulibfs.c < prev    next >
C/C++ Source or Header  |  1993-10-03  |  22KB  |  597 lines

  1. /*--------------------------------------------------------------------*/
  2. /*       u l i b f s . c                                              */
  3. /*                                                                    */
  4. /*       UUPC/extended communications driver for MS-DOS FOSSIL        */
  5. /*       based systems.                                               */
  6. /*--------------------------------------------------------------------*/
  7.  
  8. /*--------------------------------------------------------------------*/
  9. /*    Changes Copyright (c) 1989-1993 by Kendra Electronic            */
  10. /*    Wonderworks.                                                    */
  11. /*                                                                    */
  12. /*    All rights reserved except those explicitly granted by the      */
  13. /*    UUPC/extended license agreement.                                */
  14. /*--------------------------------------------------------------------*/
  15.  
  16. /*--------------------------------------------------------------------*/
  17. /*                          RCS Information                           */
  18. /*--------------------------------------------------------------------*/
  19.  
  20. /*
  21.  *    $Id: ulibfs.c 1.3 1993/10/03 22:09:09 ahd Exp $
  22.  *
  23.  *    History:
  24.  *    $Log: ulibfs.c $
  25.  * Revision 1.3  1993/10/03  22:09:09  ahd
  26.  * Use unsigned long to display speed
  27.  *
  28.  * Revision 1.2  1993/05/30  15:25:50  ahd
  29.  * Multiple driver support
  30.  *
  31.  * Revision 1.1  1993/05/30  00:01:47  ahd
  32.  * Initial revision
  33.  *
  34.  */
  35.  
  36. /*--------------------------------------------------------------------*/
  37. /*                        System include files                        */
  38. /*--------------------------------------------------------------------*/
  39.  
  40. #include <stdio.h>
  41. #include <string.h>        // For memset()
  42. #include <stdlib.h>        // For max()
  43. #include <dos.h>           // For FOSSIL interrupt calls
  44. #include <time.h>          // For sleep.h support
  45.  
  46. /*--------------------------------------------------------------------*/
  47. /*                    UUPC/extended include files                     */
  48. /*--------------------------------------------------------------------*/
  49.  
  50. #include "lib.h"
  51. #include "ulibfs.h"
  52. #include "commlib.h"
  53. #include "fossil.h"
  54. #include "catcher.h"       // For terminate processing flags
  55. #include "ssleep.h"        // For ddelay, etc.
  56.  
  57. /*--------------------------------------------------------------------*/
  58. /*                        Internal prototypes                         */
  59. /*--------------------------------------------------------------------*/
  60.  
  61. static void showModem( const short );
  62.  
  63. static void getDriverInfo( FS_INFO *fossilData);
  64.  
  65. static short blockIO( char *buffer,
  66.                       const short len,
  67.                       const char function);
  68.  
  69. /*--------------------------------------------------------------------*/
  70. /*                          Global variables                          */
  71. /*--------------------------------------------------------------------*/
  72.  
  73. static BPS currentBPS;
  74. static boolean currentDirect;
  75. static boolean carrierDetect;
  76. static boolean hangupNeeded;
  77.  
  78. currentfile();
  79.  
  80. /*--------------------------------------------------------------------*/
  81. /*    f o p e n L i n e                                               */
  82. /*                                                                    */
  83. /*    Open a fossil controlled port                                   */
  84. /*--------------------------------------------------------------------*/
  85.  
  86. int fopenline(char *name, BPS baud, const boolean direct)
  87. {
  88.    short result;
  89.    FS_INFO fossilData;         // Information returned by FOSSIL
  90.  
  91. /*--------------------------------------------------------------------*/
  92. /*                       Determine the port number                    */
  93. /*--------------------------------------------------------------------*/
  94.  
  95.    if (sscanf(name, "COM%d", &portNum) != 1)
  96.    {
  97.       printmsg(0,"Communications port must be format COMx, was %s",
  98.                 name);
  99.       panic();
  100.    }
  101.  
  102.    portNum--;                 // FOSSIL uses offset, not ordinal number
  103.  
  104. /*--------------------------------------------------------------------*/
  105. /*                   Attempt to initialize the driver                 */
  106. /*--------------------------------------------------------------------*/
  107.  
  108.    result = FSOpen( );        // Try to open the port
  109.    if ( result != FS_COOKIE )
  110.    {
  111.       printmsg(0,"fopenLine: Open failed, result %d",result );
  112.       return TRUE;            // Report failure
  113.    }
  114.  
  115. /*--------------------------------------------------------------------*/
  116. /*          Now initialize the rest of the port information           */
  117. /*--------------------------------------------------------------------*/
  118.  
  119.    ssleep(2);                 // Wait two seconds as required by V.24
  120.  
  121.    currentDirect = direct;    // Save for flow control processing
  122.    carrierDetect = FALSE;     // No modem connected yet
  123.  
  124.    flowcontrol( FALSE );      // Set no (or hardware) flow control
  125.    fSIOSpeed( baud );         // Set the port speed
  126.    traceStart( name );        // Enable line tracing
  127.  
  128.    getDriverInfo( &fossilData );
  129.  
  130.    printmsg(4,"fopenline: Driver: %Fs (revision %d)",
  131.                     fossilData.id,
  132.               (int) fossilData.revision );
  133.    printmsg(4,"fopenline: FOSSIL version %d, "
  134.               "input buffer %d, output buffer %d",
  135.               (int) fossilData.version,
  136.               (int) fossilData.inputSize,
  137.               (int) fossilData.outputSize );
  138.  
  139.    portActive = TRUE;         // Flag port is open
  140.    return FALSE;              // Report success to caller
  141.  
  142. } /* fopenLine */
  143.  
  144. /*--------------------------------------------------------------------*/
  145. /*       f s r e a d                                                  */
  146. /*                                                                    */
  147. /*       Read a specified number of bytes from the serial port        */
  148. /*--------------------------------------------------------------------*/
  149.  
  150. unsigned int fsread(char *buffer,
  151.                           unsigned int wanted,
  152.                           unsigned int timeout)
  153. {
  154.    FS_INFO fossilData;         // Information returned by FOSSIL
  155.  
  156.    time_t quit  = time( NULL ) + timeout;
  157.  
  158.    showModem( FSStatus());    // Report modem status if changed
  159.  
  160. /*--------------------------------------------------------------------*/
  161. /*                 Main loop to read data from FOSSIL                 */
  162. /*--------------------------------------------------------------------*/
  163.  
  164.    for ( ;; )
  165.    {
  166.       unsigned int pending;
  167.  
  168.       getDriverInfo( &fossilData );
  169.       pending = fossilData.inputSize - fossilData.inputFree;
  170.  
  171.       if ( pending >= wanted )
  172.       {
  173.          unsigned int moved = blockIO( buffer, wanted, FS_READBLOK );
  174.                                              // Get the data
  175.          traceData( buffer, moved, FALSE );  // Trace the data
  176.  
  177.          if ( moved < wanted)                // Promised data delivered?
  178.          {                                   // NO --> Panic (literally)
  179.             printmsg(0,"fsread: Read failed at %d of %d bytes"
  180.                        "(%d bytes available)",
  181.                         moved,
  182.                         wanted,
  183.                         pending );
  184.             panic();
  185.          }
  186.  
  187.          return pending;                            // Return success
  188.  
  189.       } /* if ( pending >= wanted ) */
  190.  
  191. /*--------------------------------------------------------------------*/
  192. /*       We don't have the data we need (yet), see if we can wait     */
  193. /*       for it.                                                      */
  194. /*--------------------------------------------------------------------*/
  195.  
  196.       if (quit <= time(NULL))             // Any time left to wait?
  197.       {
  198.          printmsg(20, "fsread: pending=%d, wanted=%d",
  199.                         pending, wanted);
  200.          return pending;                  // No --> return quietly
  201.       }
  202.  
  203.       if ( terminate_processing )         // User hit Ctrl-Break?
  204.       {
  205.          static boolean recurse = FALSE;
  206.  
  207.          if ( ! recurse )
  208.          {
  209.             printmsg(2,"fsread: User aborted processing");
  210.             recurse = TRUE;
  211.          }
  212.          return 0;
  213.  
  214.       }  /* if ( terminate_processing ) */
  215.  
  216.       if ( fossilData.inputSize < (int) wanted )   // Sanity check this ...
  217.       {                                      // last for performance reasons.
  218.          printmsg(0,"fsread: FOSSIL queue too small (%d bytes) to"
  219.                     "satisfy read of %d bytes",
  220.                     fossilData.inputSize , wanted );
  221.          panic();
  222.  
  223.       } /* if */
  224.  
  225.       ddelay(0);                          // Pause, then do it all again
  226.  
  227.    } /* for ( ;; ) */
  228.  
  229. } /* fsread */
  230.  
  231. /*--------------------------------------------------------------------*/
  232. /*       f s w r i t e                                                */
  233. /*                                                                    */
  234. /*       Write data to a FOSSIL controled serial port                 */
  235. /*--------------------------------------------------------------------*/
  236.  
  237. int fswrite(const char *data, unsigned int queued)
  238. {
  239.  
  240.    int moved;
  241.    int total;
  242.    int spin;
  243.    static int const max_spin = 20;
  244.    FS_INFO fossilData;           // Information returned by FOSSIL
  245.  
  246.    hangupNeeded = TRUE;          // Serial port is now "dirty"
  247.  
  248.    showModem( FSStatus());       // Report modem status if changed
  249.  
  250. /*--------------------------------------------------------------------*/
  251. /*                            Perform the I/O                         */
  252. /*--------------------------------------------------------------------*/
  253.  
  254.   moved = blockIO( (char *) data, queued, FS_WRITBLOK );
  255.                                  // Write the data to port
  256.  
  257.   traceData( data, moved, TRUE); // Trace our output
  258.  
  259.   if ( moved == (int) queued )   // Did it all get written out?
  260.       return moved;              // Yes --> Return gracefully
  261.  
  262.    printmsg(4,"fswrite: Wrote %d bytes of %d", moved, queued);
  263.  
  264. /*--------------------------------------------------------------------*/
  265. /*       The FOSSIL driver didn't have enough room in its buffer;     */
  266. /*       determine how much we did send.                              */
  267. /*--------------------------------------------------------------------*/
  268.  
  269.    getDriverInfo( &fossilData );
  270.  
  271.    total = moved;
  272.    queued -= moved;                 // We only need to still move this
  273.  
  274. /*--------------------------------------------------------------------*/
  275. /*       Block processing for a limited amount of time if we need     */
  276. /*       more room in the FOSSIL buffer.                              */
  277. /*--------------------------------------------------------------------*/
  278.  
  279.    spin = max_spin;
  280.  
  281.    while( spin && queued )
  282.    {
  283.       int wait;
  284.       int needed;
  285.  
  286.       needed = max(fossilData.outputSize / 2, (int) queued );
  287.                            /* Minimize thrashing by requiring
  288.                               big chunks */
  289.  
  290.       wait = (int) ((long) needed * 10000L / (long) currentBPS);
  291.                            /* Compute time in milliseconds
  292.                               assuming 10 bits per byte           */
  293.  
  294.       printmsg(4,"fswrite: Waiting %d ms for %d bytes in queue"
  295.                   ", pass %d",
  296.                   wait, needed, spin);
  297.  
  298.       ddelay( wait );      /* Actually perform the wait           */
  299.  
  300.       moved = blockIO( (char *) data + total, queued, FS_WRITBLOK );
  301.                                                 // Write the data
  302.       traceData( data + total, moved, TRUE);    // Trace our output
  303.  
  304.       if ( moved != 0)
  305.          spin--;           /* No progress, consider timing out    */
  306.       else {
  307.          total += moved;
  308.          queued -= moved;
  309.       }                   /* Update our progress                 */
  310.  
  311.    } /* while(spin && wanted ) */
  312.  
  313. /*--------------------------------------------------------------------*/
  314. /*             Handle buffer overflow which never went away           */
  315. /*--------------------------------------------------------------------*/
  316.  
  317.    if ( queued )
  318.    {
  319.       printmsg(0,"fswrite: Buffer overflow, needed %d bytes",
  320.                   queued);
  321.       return 0;
  322.    } /* if ( queued ) */
  323.  
  324. /*--------------------------------------------------------------------*/
  325. /*                       Return success to caller                     */
  326. /*--------------------------------------------------------------------*/
  327.  
  328.    return total;
  329.  
  330. } /* fswrite */
  331.  
  332. /*--------------------------------------------------------------------*/
  333. /*    f s s e n d b r k                                               */
  334. /*                                                                    */
  335. /*    Send a break to the remote system                               */
  336. /*--------------------------------------------------------------------*/
  337.  
  338. void fssendbrk(unsigned int duration)
  339. {
  340.  
  341.    FSBreak( TRUE );
  342.    printmsg(4, "fssendbrk: %d", duration);
  343.    ddelay( duration * 100 );
  344.    FSBreak( FALSE );
  345.  
  346. } /* fssendbrk */
  347.  
  348. /*--------------------------------------------------------------------*/
  349. /*    f c l o s e l i n e                                             */
  350. /*                                                                    */
  351. /*    Close a FOSSIL controlled port                                  */
  352. /*--------------------------------------------------------------------*/
  353.  
  354. void fcloseline(void)
  355. {
  356.    if (!portActive)
  357.       panic();
  358.  
  359.    portActive = FALSE;        // Flag port closed for error handler
  360.  
  361.    FSFlushXmit();             // Drop XMIT queue if not empty
  362.    FSFlushRecv();             // Drop Recv queue as well
  363.  
  364.    FSDTR( FALSE );
  365.    ddelay(500);               // Required for V.24
  366.  
  367.    FSClose();
  368.    traceStop();
  369.  
  370. } /* fcloseline */
  371.  
  372. /*--------------------------------------------------------------------*/
  373. /*    F S S e t S p e e d                                             */
  374. /*                                                                    */
  375. /*    Set current speed port; also sets parity and associated         */
  376. /*    parameters.                                                     */
  377. /*--------------------------------------------------------------------*/
  378.  
  379. void fSIOSpeed(BPS bps)
  380. {
  381.  
  382.    static const long rates[] =
  383.          { 19200, 38400, 300, 600, 1200, 2400, 4800, 9600, -19200 };
  384.  
  385.    short speed = 0;        // Actual value used by FOSSIL for speed
  386.  
  387.    short best = 3;
  388.  
  389.    while( (rates[speed] > 0) && (rates[speed] != (long) bps ))
  390.    {
  391.       if ( (rates[speed] / 100) == ((long) bps / 100) )
  392.          best = speed;
  393.  
  394.       speed++;
  395.    }
  396.  
  397.    if ( rates[speed] < 0 )
  398.    {
  399.       printmsg(0,"fSIOSpeed: Invalid modem speed %lu, using %lu",
  400.                   (unsigned long) bps,
  401.                   (unsigned long) rates[speed]);
  402.       speed = best;
  403.    }
  404.  
  405.    printmsg(4,"fSIOSspeed: Changing port speed from %lu BPS to %lu BPS",
  406.                (unsigned long) currentBPS,
  407.                (unsigned long) rates[speed]);
  408.  
  409.    FSSetSpeed( speed, FS_NO_PARITY, FS_STOPBIT_1, FS_CHARLEN_8);
  410.  
  411.    showModem( FSStatus());    // Report modem status if changed
  412.  
  413.    currentBPS = rates[speed];
  414.  
  415. } /* fSIOSpeed */
  416.  
  417. /*--------------------------------------------------------------------*/
  418. /*       f f l o w c o n t r o l                                      */
  419. /*                                                                    */
  420. /*       Enable flow control for FOSSIL driven port                   */
  421. /*--------------------------------------------------------------------*/
  422.  
  423. void fflowcontrol( boolean flow )
  424. {
  425.    printmsg(4,"fflowcontrol: %sabling in-band flow control",
  426.                flow ? "en" : "dis");
  427.    if ( flow )
  428.       FSFlowControl( FS_XONXMIT | FS_XONRECV );
  429.    else if ( currentDirect )    // Direct means no flow control
  430.       FSFlowControl( FS_NOFLOW );
  431.    else
  432.       FSFlowControl( FS_CTSRTS );
  433.  
  434. } /* fflowcontrol */
  435.  
  436. /*--------------------------------------------------------------------*/
  437. /*       f h a n g u p                                                */
  438. /*                                                                    */
  439. /*       Perform hangup via DTR drop on FOSSIL controlled port        */
  440. /*--------------------------------------------------------------------*/
  441.  
  442. void fhangup( void )
  443. {
  444.    if (!hangupNeeded)
  445.       return;
  446.  
  447.    hangupNeeded = FALSE;
  448.  
  449.    FSFlushXmit();             // Drop XMIT queue if not empty
  450.    FSFlushRecv();             // Drop Recv queue as well
  451.  
  452.    FSDTR( FALSE );         /* Hang the phone up                         */
  453.    ddelay(500);            /* Really only need 250 milliseconds         */
  454.    FSDTR( TRUE );          /* Bring the modem back on-line              */
  455.    ddelay(2000);           /* Now wait for the poor thing to recover    */
  456.                            /* two seconds is required by V.24           */
  457.  
  458.    printmsg(3,"fhangup: complete.");
  459.    carrierDetect = FALSE;  /* No modem connected yet                    */
  460.  
  461. } /* fhangup */
  462.  
  463. /*--------------------------------------------------------------------*/
  464. /*    f G e t S p e e d                                               */
  465. /*                                                                    */
  466. /*    Return current port speed                                       */
  467. /*--------------------------------------------------------------------*/
  468.  
  469. BPS fGetSpeed( void )
  470. {
  471.    return currentBPS;
  472. }
  473.  
  474. /*--------------------------------------------------------------------*/
  475. /*       f C D                                                        */
  476. /*                                                                    */
  477. /*       Determine if Carrier Detect has dropped                      */
  478. /*--------------------------------------------------------------------*/
  479.  
  480. boolean fCD( void )
  481. {
  482.    boolean saveCD = carrierDetect;
  483.  
  484.    short status = FSStatus();
  485.  
  486.    showModem( status );
  487.    if ( status & FS_STAT_DCD )
  488.       carrierDetect = TRUE;
  489.  
  490.    if ((! saveCD) || carrierDetect)
  491.       return TRUE;
  492.  
  493.    printmsg(0,"fCD: Lost carrier detect");
  494.    return FALSE;
  495.  
  496. } /* fCD */
  497.  
  498. /*--------------------------------------------------------------------*/
  499. /*       s h o w M o d e m                                            */
  500. /*                                                                    */
  501. /*       Display current modem status                                 */
  502. /*--------------------------------------------------------------------*/
  503.  
  504. #define mannounce(flag, bits, text ) ((flag & bits) ? text : "" )
  505.  
  506. static void showModem( const short status )
  507. {
  508.    static int old_status = 0xDEAD;
  509.  
  510.    if ( debuglevel < 4 )
  511.       return;
  512.  
  513.    if (status == old_status)
  514.       return;
  515.  
  516.    printmsg(0, "showModem: %#04x%s%s%s%s%s",
  517.       status,
  518.       mannounce(FS_STAT_DCD,        status, "\tCarrier Detect"),
  519.       mannounce(FS_STAT_OVERRUN,    status, "\tR-Overrun"),
  520.       mannounce(FS_STAT_INQUEUED,   status, "\tR-Pending"),
  521.       mannounce(FS_STAT_OUTPROOM,   status, "\tX-Free"),
  522.       mannounce(FS_STAT_OUTPEMPT,   status, "\tX-Empty")
  523.       );
  524.  
  525.    old_status = status;
  526.  
  527. } /* showModem */
  528.  
  529. /*--------------------------------------------------------------------*/
  530. /*       g e t D r i v e r I n f o                                    */
  531. /*                                                                    */
  532. /*       Return current FOSSIL driver information                     */
  533. /*--------------------------------------------------------------------*/
  534.  
  535. static void getDriverInfo( FS_INFO *fossilData)
  536. {
  537.    union REGS regs;
  538.    struct SREGS sregs;
  539.  
  540.    regs.h.ah = FS_DRIVINFO;            // Get driver information
  541.    regs.x.cx = sizeof *fossilData;     // Into buffer this long
  542.    sregs.es  = FP_SEG( fossilData );   // Use segment of buffer
  543.    regs.x.di = FP_OFF( fossilData );   // Use offset of buffer
  544.    regs.x.dx = portNum;                // For this port
  545.  
  546.    int86x( FS_INTERRUPT, ®s, ®s, &sregs);
  547.  
  548.    if ( regs.x.ax != sizeof *fossilData )
  549.    {
  550.       printmsg(0,"getDriverInfo: Read of FOSSIL information failed, "
  551.                  " %d bytes returned", regs.x.ax  );
  552.       panic();
  553.    }
  554.  
  555. } /* getDriverInfo */
  556.  
  557. /*--------------------------------------------------------------------*/
  558. /*       b l o c k I O                                                */
  559. /*                                                                    */
  560. /*       Perform block I/O between memory and the FOSSIL data         */
  561. /*       queues                                                       */
  562. /*--------------------------------------------------------------------*/
  563.  
  564. static short blockIO( char *buffer, const short len, const char function)
  565. {
  566.    union REGS regs;
  567.    struct SREGS sregs;
  568.  
  569.    regs.x.dx = portNum;                // Perform function against port
  570.  
  571.    regs.h.ah = FS_STATPORT;            // First, set up to get status
  572.    int86( FS_INTERRUPT, ®s, ®s); // ... get the info ...
  573.    showModem ( regs.x.ax );            // ... and report it
  574.  
  575.    regs.h.ah = function;               // Input or output function
  576.    regs.x.cx = len;                    // Into buffer this long
  577.    sregs.es = FP_SEG( buffer);         // Use segment of the buffer
  578.    regs.x.di = FP_OFF( buffer );       // Use offset of buffer
  579.  
  580.    int86x( FS_INTERRUPT, ®s, ®s, &sregs);
  581.  
  582.    if ( len > (short) regs.x.ax )
  583.       printmsg(4,"blockIO: Buffer %d bytes, only moved %d bytes",
  584.                  len,
  585.                  regs.x.ax );
  586.    else if ( len < (short) regs.x.ax )
  587.    {
  588.       printmsg(4,"blockIO: BUFFER (%d bytes) OVERRUN, moved %d bytes",
  589.                  len,
  590.                  regs.x.ax );
  591.       panic();
  592.    }
  593.  
  594.    return (short) regs.x.ax;           // Return bytes moved
  595.  
  596. } /* blockIO */
  597.